#pragma once
#include <iostream>
using namespace std;

class person
{
public:
    virtual void buy_ticket() { cout << "person full price" << endl; }
};

class student : public person
{
public:
    virtual void buy_ticket() { cout << "child half price" << endl; }
    int _s;
};

void func(person& p)
{
    p.buy_ticket();
}

void test_4()
{
    // base b;
    // cout << sizeof(base) << endl;
    
    person p;
    student s;

    person& rp = s;

    func(p);
    func(s);
}


typedef void(*vf_t)();

void print_vftable(vf_t* vft)
{
    for (int i = 0; vft[i]; i++)
    {
        printf("vft[%d]=0x%p->", i, vft[i]);
        vft[i]();
    }
    printf("\n");
}


namespace singleInheritance{
class A {
public:
    virtual void vFunc1() { cout << "A::vFunc1()" << endl; }
    virtual void vFunc2() { cout << "A::vFunc2()" << endl; }
protected:
    int _a;
};
class B : public A {
public:
    virtual void vFunc1() { cout << "B::vFunc1()" << endl; } //重写vFunc1
    virtual void vFunc3() { cout << "B::vFunc3()" << endl; }
    virtual void vFunc4() { cout << "B::vFunc4()" << endl; }
protected:
    int _b;
};
void print()
{
    A a;
    B b;
    vf_t* vft_a = *(vf_t**)&a;
    vf_t* vft_b = *(vf_t**)&b;
    print_vftable(vft_a);
    print_vftable(vft_b);
}
}

namespace mutipleInheritance {
class A {
public:
    virtual void vFunc1() { cout << "A::vFunc1()" << endl; }
    virtual void vFunc2() { cout << "A::vFunc2()" << endl; }
    int _a;
};
class B {
public:
    virtual void vFunc1() { cout << "B::vFunc1()" << endl; }
    virtual void vFunc2() { cout << "B::vFunc2()" << endl; }
    int _b;
};
class C : public A, public B {
public:
    virtual void vFunc1() { cout << "C::vFunc1()" << endl; }
    virtual void vFunc3() { cout << "C::vFunc3()" << endl; } // new
    int _c;
};
void print()
{
    C c;
    vf_t* vft_from_a = *(vf_t**)&c;
    // vf_t* vft_from_b = *(vf_t**)((char*)&c + sizeof(A));
    B* pc_from_b = &c;
    vf_t* vft_from_b = *(vf_t**)(pc_from_b);
    print_vftable(vft_from_a);
    print_vftable(vft_from_b);

    A* pa = &c;
    B* pb = &c;

    pa->vFunc1();
    pb->vFunc1();
}
}

namespace diamondInheritance {
class A {
public:
	virtual void vFunc1() { cout << "A::vFunc1()" << endl; }
	virtual void vFunc2() { cout << "A::vFunc2()" << endl; }
	int _a;
};
class B : public A {
public:
	virtual void vFunc1() { cout << "B::vFunc1()" << endl; }
	virtual void vFunc2() { cout << "B::vFunc2()" << endl; }
	int _b;
};
class C : public A {
public:
	virtual void vFunc1() { cout << "C::vFunc1()" << endl; }
	virtual void vFunc3() { cout << "C::vFunc3()" << endl; }
	int _c;
};
class D : public B, public C {
public:
	virtual void vFunc1() { cout << "C::vFunc1()" << endl; } 
	virtual void vFunc4() { cout << "C::vFunc3()" << endl; }
	int _d;
};
void print()
{
    // print_vftable<A>(); 
    // print_vftable<B>(); 
    // print_vftable<C>(); 
    // print_vftable<D>(); 
}
}

namespace virtualInheritance {
class A {
public:
	virtual void vFunc1() { cout << "A::vFunc1()" << endl; }
	virtual void vFunc2() { cout << "A::vFunc2()" << endl; }
	int _a;
};
class B : public A {
public:
	virtual void vFunc1() { cout << "B::vFunc1()" << endl; } 
	virtual void vFunc2() { cout << "B::vFunc2()" << endl; }
	int _b;
};
class C : public A {
public:
	virtual void vFunc1() { cout << "C::vFunc1()" << endl; }
	virtual void vFunc3() { cout << "C::vFunc3()" << endl; }
	int _c;
};
class D : virtual public B, virtual public C {
public:
	virtual void vFunc1() { cout << "C::vFunc1()" << endl; }
	virtual void vFunc4() { cout << "C::vFunc3()" << endl; }
	int _d;
};
void print()
{
    // print_vftable<A>(); 
    // print_vftable<B>(); 
    // print_vftable<C>(); 
    // print_vftable<D>(); 
}
}

void test_5()
{
	//singleInheritance::print();
    mutipleInheritance::print();
    //diamondInheritance::print();
    //virtualInheritance::print();
}
